package com.huan.springcloud.overrided.exists.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 替换掉Spring容器中已经存在的Bean
 * ProductService是通过@Service注入到Spring容器中的，但是我觉得这个写的不好，需要替换成自己写的BananaProductService实现
 */
@SpringBootApplication
public class SpringbootOverrideExistsBeanApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringbootOverrideExistsBeanApplication.class, args);
        applicationContext.getBean(ProductService.class).addProduct();
    }
}

interface ProductService {
    void addProduct();
}

@Component("productService")
class AppleProductService implements ProductService {
    @Override
    public void addProduct() {
        System.out.println("添加苹果");
    }
}

class BananaProductService implements ProductService {
    @Autowired
    private ApplicationContext applicationContext;

    @PostConstruct
    public void init() {
        System.out.println("我替换了默认的实现");
    }

    @Override
    public void addProduct() {
        System.out.println("添加香蕉" + applicationContext.getClass());
    }
}

/**
 * 实现 Ordered接口，指定执行顺序
 */
@Component
class OverrideExistsBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        String beanName = "productService";
        if (registry.containsBeanDefinition(beanName)) {
            registry.removeBeanDefinition(beanName);
            GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
            beanDefinition.setBeanClass(BananaProductService.class);
            registry.registerBeanDefinition(beanName, beanDefinition);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("aa");
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}